function recurFreeze(obj) {
  // 冻结当前对象的所有原始值属性
  Object.freeze(obj);
  for (const key in obj) {
    // 当属性为对象时需要递归执行冻结方法
    // 需要考虑到 typeof null 时也是输出 'object'
    // 因此需要排除null的情况
    // (obj[key] !== null && typeof key === 'object') && recurFreeze(obj[key]);
    // 等同于:
    if (obj[key] !== null && typeof obj[key] === 'object') {
      recurFreeze(obj[key]);
    }
  }
}

const obj = {
  name: 'zhangsan',
  info: {
    address: 'somewhere'
  }
}

recurFreeze(obj);

obj.name = 'lisi';
obj.info.address = 'here';

console.log(obj); // { name: 'zhangsan', info: { address: 'somewhere' } }